package com.zjhn.ds.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zjhn.ds.common.BizResult;
import com.zjhn.ds.common.Constant;
import com.zjhn.ds.common.PageResult;
import com.zjhn.ds.common.annotate.IgnoreTenant;
import com.zjhn.ds.domain.dto.pc.DsControlCenterDto;
import com.zjhn.ds.domain.dto.pc.DsDeviceMonitorDto;
import com.zjhn.ds.domain.dto.pc.DsDeviceStationDto;
import com.zjhn.ds.domain.dto.pc.DsMonitorCenterDto;
import com.zjhn.ds.domain.dto.pc.PcMonitorDetailDto;
import com.zjhn.ds.domain.dto.pc.PcMonitorDto;
import com.zjhn.ds.domain.dto.pc.PcRunMonitorDto;
import com.zjhn.ds.domain.dto.pc.PcRunMonitorExcelDto;
import com.zjhn.ds.domain.dto.pc.SpotCheckDetailDto;
import com.zjhn.ds.domain.dto.pc.SpotCheckDetailExcelDto;
import com.zjhn.ds.domain.dto.pc.SpotCheckStatisticsDto;
import com.zjhn.ds.domain.dto.pc.SpotCheckStatisticsExcelDto;
import com.zjhn.ds.domain.dto.pc.StationPositionDto;
import com.zjhn.ds.domain.dto.pc.StationStatusDto;
import com.zjhn.ds.domain.entity.erp.ProTaskDetail;
import com.zjhn.ds.domain.entity.jlw.AssignTask;
import com.zjhn.ds.domain.entity.jlw.Group;
import com.zjhn.ds.domain.entity.jlw.GroupSpinner;
import com.zjhn.ds.domain.entity.jlw.GroupStation;
import com.zjhn.ds.domain.entity.jlw.ReportRecord;
import com.zjhn.ds.domain.entity.jlw.Spinner;
import com.zjhn.ds.domain.entity.jlw.SpotCheck;
import com.zjhn.ds.domain.entity.jlw.Station;
import com.zjhn.ds.domain.entity.jlw.StationClassRecord;
import com.zjhn.ds.domain.entity.jlw.SwipeCardInfo;
import com.zjhn.ds.domain.entity.jlw.Workshop;
import com.zjhn.ds.domain.entity.jlw.WorkshopClasses;
import com.zjhn.ds.domain.vo.SpinnerVo;
import com.zjhn.ds.domain.vo.StationMakeTimeVo;
import com.zjhn.ds.domain.vo.StationStatusVo;
import com.zjhn.ds.domain.vo.StationVo;
import com.zjhn.ds.domain.vo.StationWithGroupNameVo;
import com.zjhn.ds.domain.vo.TradeOrderVo;
import com.zjhn.ds.mapper.AssignTaskMapper;
import com.zjhn.ds.mapper.GroupMapper;
import com.zjhn.ds.mapper.GroupSpinnerMapper;
import com.zjhn.ds.mapper.GroupStationMapper;
import com.zjhn.ds.mapper.ProTaskDetailMapper;
import com.zjhn.ds.mapper.ReportRecordMapper;
import com.zjhn.ds.mapper.SpinnerMapper;
import com.zjhn.ds.mapper.SpotCheckMapper;
import com.zjhn.ds.mapper.StationClassRecordMapper;
import com.zjhn.ds.mapper.StationMapper;
import com.zjhn.ds.mapper.SwipeCardInfoMapper;
import com.zjhn.ds.mapper.WorkshopClassesMapper;
import com.zjhn.ds.mapper.WorkshopMapper;
import com.zjhn.ds.param.PcMonitorPageParam;
import com.zjhn.ds.param.SpotCheckDetailParam;
import com.zjhn.ds.param.SpotCheckStatisticsParam;
import com.zjhn.ds.param.StationRecordMonitorParam;
import com.zjhn.ds.param.StationStatusParam;
import com.zjhn.ds.service.MonitorService;
import com.zjhn.ds.utils.CommonUtil;
import com.zjhn.ds.utils.RestHighLevelUtils;
import com.zjhn.ds.utils.UserUtil;
import com.zjhn.ds.utils.base.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @BelongsProject: ds_jlw
 * @BelongsPackage: com.zjhn.ds.service.impl
 * @Author: sxt
 * @CreateTime: 2023-11-22  14:58
 * @Description:
 * @Version: 1.0
 */
@Slf4j
@Service
public class MonitorServiceImpl implements MonitorService {

    @Resource
    private CommonUtil commonUtil;

    @Resource
    private StationMapper stationMapper;

    @Resource
    private SwipeCardInfoMapper swipeCardInfoMapper;

    @Resource
    private WorkshopMapper workshopMapper;

    @Resource
    private WorkshopClassesMapper workshopClassesMapper;

    @Resource
    private GroupMapper groupMapper;

    @Resource
    private GroupStationMapper groupStationMapper;

    @Resource
    private GroupSpinnerMapper groupSpinnerMapper;

    @Resource
    private AssignTaskMapper assignTaskMapper;

    @Resource
    private SpinnerMapper spinnerMapper;

    @Resource
    private ReportRecordMapper reportRecordMapper;

    @Resource
    private ProTaskDetailMapper proTaskDetailMapper;

    @Resource
    private StationClassRecordMapper stationClassRecordMapper;

    @Resource
    private RestHighLevelUtils restHighLevelUtils;

    @Resource
    private SpotCheckMapper spotCheckMapper;

    @Resource
    private UserUtil userUtil;

    /**
     * 迪赛针织设备运行监控台
     *
     * @return
     */
    @IgnoreTenant
    @Override
    public BizResult<List<DsDeviceMonitorDto>> dsDeviceMonitor(List<String> groupIds) {
        Map<String, SpinnerVo> spinnerVoMap = new HashMap<>();
        Map<String, List<GroupSpinner>> groupSpinnerMap = new HashMap<>();
        Map<String, List<GroupStation>> groupStationMap = new HashMap<>();
        Map<String, SwipeCardInfo> swipeCardInfoMap = new HashMap<>();
        Map<String, List<ReportRecord>> reportRecordMap = new HashMap<>();
        Map<String, Integer> taskStatusMap = new HashMap<>();
        Map<String, StationClassRecord> stationClassRecordMap = new HashMap<>();

        // 当前班次
        WorkshopClasses workshopClasses = commonUtil.getWorkshopClasses();
        if (workshopClasses == null)
            return BizResult.fail("班次不存在");
        String currentDay = DateUtil.getCurrentDay(workshopClasses.getStartTime(), workshopClasses.getEndTime(), new Date());

        List<Group> groups = groupMapper.selectList(
                new QueryWrapper<Group>()
                        .in("id", groupIds)
                        .orderByAsc("sort")
                        .eq("TenantId", "08A69B3C-9A56-4407-8A08-27B21B6B0DD8")
        );
        if (groups.size() > 0) {
            List<GroupStation> groupStations = groupStationMapper.selectList(new QueryWrapper<GroupStation>().in("group_id", groupIds));
            if (groupStations.size() > 0) {
                groupStationMap.putAll(groupStations.stream().collect(Collectors.groupingBy(GroupStation::getGroupId)));

                List<String> stationIds = groupStations.stream().map(GroupStation::getStationId).collect(Collectors.toList());
                // 机台班次时长
                List<StationClassRecord> stationClassRecords = stationClassRecordMapper.selectList(
                        new QueryWrapper<StationClassRecord>()
                                .in("station_id", stationIds)
                                .eq("workshop_class_id", workshopClasses.getId())
                                .eq("current_day", currentDay));
                if (stationClassRecords.size() > 0)
                    stationClassRecordMap.putAll(stationClassRecords.stream().collect(Collectors.toMap(StationClassRecord::getStationId, c -> c)));

                // 刷卡信息
                List<SwipeCardInfo> swipeCardInfos = swipeCardInfoMapper
                        .selectList(
                                new QueryWrapper<SwipeCardInfo>()
                                        .in("station_id", stationIds)
                        );
                if (swipeCardInfos.size() > 0) {
                    swipeCardInfoMap.putAll(swipeCardInfos.stream().collect(Collectors.toMap(SwipeCardInfo::getStationId, c -> c)));

                    // 进度
                    Set<String> assignTaskIds = swipeCardInfos.stream().map(SwipeCardInfo::getAssignTaskId).collect(Collectors.toSet());
                    List<AssignTask> assignTasks = assignTaskMapper.selectBatchIds(assignTaskIds);

                    Set<String> proTaskDetailIds = assignTasks.stream().map(AssignTask::getTaskDetailId).collect(Collectors.toSet());
                    List<ProTaskDetail> proTaskDetails = proTaskDetailMapper.selectBatchIds(proTaskDetailIds);
                    Map<String, ProTaskDetail> proTaskDetailMap = proTaskDetails.stream().collect(Collectors.toMap(ProTaskDetail::getId, c -> c));

                    List<AssignTask> all = assignTaskMapper.selectList(new QueryWrapper<AssignTask>().in("task_detail_id", proTaskDetailIds));
                    Map<String, List<AssignTask>> assignTaskGroup = all.stream().collect(Collectors.groupingBy(AssignTask::getTaskDetailId));
                    for (String taskDetailId : assignTaskGroup.keySet()) {
                        ProTaskDetail proTaskDetail = proTaskDetailMap.get(taskDetailId);
                        if (proTaskDetail == null)
                            return BizResult.fail("对应生产明细不存在");

                        List<AssignTask> collect = assignTaskGroup.get(taskDetailId);
                        BigDecimal taskFinishQty = BigDecimal.ZERO;
                        if (collect.size() > 0)
                            taskFinishQty = collect.stream().map(AssignTask::getCompleteQty).reduce(BigDecimal.ZERO, BigDecimal::add);

                        int taskStatus = 1;
                        if (proTaskDetail.getWarnQty() != null) {
                            if (taskFinishQty.compareTo(BigDecimal.valueOf(proTaskDetail.getNumber())) >= 0)
                                taskStatus = 3;
                            else if (taskFinishQty.compareTo(proTaskDetail.getWarnQty()) >= 0)
                                taskStatus = 2;
                        }
                        taskStatusMap.put(taskDetailId, taskStatus);
                    }
                }

                // 报工信息
                List<ReportRecord> reportRecords = reportRecordMapper.selectList(
                        new QueryWrapper<ReportRecord>()
                                .in("station_id", stationIds)
                                .apply("CONVERT(DATE, create_time) = CONVERT(DATE, GETDATE())")
                );
                if (reportRecords.size() > 0)
                    reportRecordMap.putAll(reportRecords.stream().collect(Collectors.groupingBy(ReportRecord::getStationId)));
            }

            List<GroupSpinner> groupSpinners = groupSpinnerMapper.selectList(new QueryWrapper<GroupSpinner>().in("group_id", groupIds));
            if (groupSpinners.size() > 0) {
                groupSpinnerMap.putAll(groupSpinners.stream().collect(Collectors.groupingBy(GroupSpinner::getGroupId)));

                List<String> spinnerIds = groupSpinners.stream().map(GroupSpinner::getGroupId).collect(Collectors.toList());
                List<SpinnerVo> spinnerVos = spinnerMapper.selectInfoByIds(spinnerIds);
                if (spinnerVos.size() > 0)
                    spinnerVoMap.putAll(spinnerVos.stream().collect(Collectors.toMap(SpinnerVo::getSpinnerId, c -> c)));
            }
        }

        List<DsDeviceMonitorDto> res = new ArrayList<>();
        for (Group group : groups) {
            SpinnerVo spinnerVo = null;
            List<GroupSpinner> groupSpinners = groupSpinnerMap.get(group.getId());
            if (groupSpinners != null)
                spinnerVo = spinnerVoMap.get(groupSpinners.get(0).getSpinnerId());

            Integer stopQty = 0; // 关机
            Integer runQty = 0; // 正常
            Integer idleQty = 0; // 待机
            Integer faultQty = 0; // 故障
            List<DsDeviceStationDto> devices = new ArrayList<>();
            List<GroupStation> groupStations = groupStationMap.get(group.getId());
            if (groupStations != null) {
                for (GroupStation groupStation : groupStations) {
                    StationVo station = commonUtil.getStationById(groupStation.getStationId());
                    if (station == null)
                        return BizResult.fail("机台信息不存在");

                    // redis机台状态判断
                    Integer status = commonUtil.getStationStatus(station.getId());
                    if (status == 0) stopQty++;
                    else if (status == 1) runQty++;
                    else if (status == 2) idleQty++;
                    else if (status == 3) faultQty++;

                    // 获取当前刷卡信息
                    SwipeCardInfo swipeCardInfo = swipeCardInfoMap.get(station.getId());

                    // 获取报工信息
                    List<ReportRecord> reportRecords = reportRecordMap.get(station.getId());

                    // mac地址
                    String macAddress = null;
                    String equipmentId = commonUtil.getBindInfoById(station.getId());
                    if (StringUtils.isNotBlank(equipmentId))
                        macAddress = commonUtil.getEquipmentById(equipmentId).getOutreachDevice();

                    // 机台时长
                    StationClassRecord stationClassRecord = stationClassRecordMap.get(station.getId());

                    devices.add(DsDeviceStationDto.builder()
                            .stationId(station.getId())
                            .stationCode(station.getStationCode())
                            .styleCode(swipeCardInfo == null ? null : swipeCardInfo.getStyleCode())
                            .oee(stationClassRecord == null ? BigDecimal.ZERO : stationClassRecord.getOee())
                            .produce(
                                    reportRecords == null ?
                                            BigDecimal.ZERO :
                                            reportRecords.stream()
                                                    .map(ReportRecord::getBookJobQty)
                                                    .reduce(BigDecimal.ZERO, BigDecimal::add))
                            .status(status)
                            .taskStatus(swipeCardInfo == null ? null : taskStatusMap.get(swipeCardInfo.getProTaskDetailId()))
                            .macAddress(macAddress)
                            .build());
                }
            }
            devices.sort((o1, o2) -> {
                String[] parts1 = o1.getStationCode().split("-");
                String[] parts2 = o2.getStationCode().split("-");

                int num1 = Integer.parseInt(parts1[0].substring(1) + parts1[1] + parts1[2]);
                int num2 = Integer.parseInt(parts2[0].substring(1) + parts2[1] + parts2[2]);

                return Integer.compare(num1, num2);
            });

            res.add(DsDeviceMonitorDto.builder()
                    .groupId(group.getId())
                    .groupName(group.getGroupName())
                    .spinnerId(spinnerVo == null ? null : spinnerVo.getSpinnerId())
                    .spinnerName(spinnerVo == null ? null : spinnerVo.getRealName())
                    .avatar(spinnerVo == null ? null : spinnerVo.getAvatar())
                    .produceQty(
                            devices.size() == 0 ?
                                    BigDecimal.ZERO :
                                    devices.stream()
                                            .map(DsDeviceStationDto::getProduce)
                                            .reduce(BigDecimal.ZERO, BigDecimal::add))
                    .stopQty(stopQty)
                    .runQty(runQty)
                    .idleQty(idleQty)
                    .faultQty(faultQty)
                    .list(devices)
                    .build());
        }

        return BizResult.success(res);
    }

    /**
     * 迪赛针织生产指挥中心
     *
     * @return
     */
    @IgnoreTenant
    @Override
    public BizResult<DsControlCenterDto> dsControlCenter() {
        Workshop workshop = workshopMapper.selectById("523cd11213f4f82407b75880f941ee88");
        if (workshop == null)
            return BizResult.fail("车间不存在");

        List<Station> stations = stationMapper.selectList(new QueryWrapper<Station>().eq("workshop_id", workshop.getId()));
        Integer stopQty = 0;
        Integer runQty = 0;
        Integer idleQty = 0;
        Integer faultQty = 0;
        for (Station station : stations) {
            Integer status = commonUtil.getStationStatus(station.getId());
            if (status == 0) stopQty++;
            else if (status == 1) runQty++;
            else if (status == 2) idleQty++;
            else if (status == 3) faultQty++;
        }

        List<ReportRecord> todayRecords = reportRecordMapper.selectList(
                new QueryWrapper<ReportRecord>().apply("CONVERT(DATE, create_time) = CONVERT(DATE, GETDATE())"));
        List<ReportRecord> monthRecords = reportRecordMapper.selectList(new QueryWrapper<ReportRecord>()
                .apply("YEAR(create_time) = YEAR(GETDATE())")
                .apply("MONTH(create_time) = MONTH(GETDATE())"));


        return BizResult.success(
                DsControlCenterDto.builder()
                        .workshopId(workshop.getId())
                        .stationQty(stations.size())
                        .stopQty(stopQty)
                        .runQty(runQty)
                        .idleQty(idleQty)
                        .faultQty(faultQty)
                        .produceQty(
                                todayRecords.size() == 0 ?
                                        BigDecimal.ZERO :
                                        todayRecords.stream()
                                                .map(ReportRecord::getBookJobQty)
                                                .reduce(BigDecimal.ZERO, BigDecimal::add))
                        .produceMonthQty(
                                monthRecords.size() == 0 ?
                                        BigDecimal.ZERO :
                                        monthRecords.stream()
                                                .map(ReportRecord::getBookJobQty)
                                                .reduce(BigDecimal.ZERO, BigDecimal::add))
                        .build());
    }

    /**
     * 迪赛针织编制车间现场监控中心
     *
     * @return
     */
    @IgnoreTenant
    @Override
    public BizResult<DsMonitorCenterDto> dsMonitorCenter() {
        Workshop workshop = workshopMapper.selectById("523cd11213f4f82407b75880f941ee88");
        if (workshop == null)
            return BizResult.fail("车间不存在");

        List<Station> stations = stationMapper.selectList(
                new QueryWrapper<Station>()
                        .eq("workshop_id", workshop.getId())
                        .eq("TenantId", "08A69B3C-9A56-4407-8A08-27B21B6B0DD8")
        );

        Integer stopQty = 0;
        Integer runQty = 0;
        Integer idleQty = 0;
        Integer faultQty = 0;
        List<StationPositionDto> list = new ArrayList<>();
        for (Station station : stations) {
            Integer status = commonUtil.getStationStatus(station.getId());
            if (status == 0) stopQty++;
            else if (status == 1) runQty++;
            else if (status == 2) idleQty++;
            else if (status == 3) faultQty++;

            String macAddress = null;
            String equipmentId = commonUtil.getBindInfoById(station.getId());
            if (StringUtils.isNotBlank(equipmentId))
                macAddress = commonUtil.getEquipmentById(equipmentId).getOutreachDevice();


            list.add(StationPositionDto.builder()
                    .stationId(station.getId())
                    .stationCode(station.getStationCode())
                    .macAddress(macAddress)
                    .status(commonUtil.getStationStatus(station.getId()))
                    .build());

        }

        return BizResult.success(
                DsMonitorCenterDto.builder()
                        .stationQty(stations.size())
                        .stopQty(stopQty)
                        .runQty(runQty)
                        .idleQty(idleQty)
                        .faultQty(faultQty)
                        .list(list)
                        .build());
    }

    /**
     * pc端机台监控页面
     *
     * @param param
     * @return
     */
    @Override
    public BizResult<PageResult<PcMonitorDto>> pcStationMonitor(PcMonitorPageParam param) {
        Map<String, String> groupMap = new HashMap<>();
        Map<String, String> groupSpinnerMap = new HashMap<>();
        List<GroupStation> groupStations = new ArrayList<>();
        Map<String, SwipeCardInfo> swipeCardInfoMap = new HashMap<>();
        Map<String, AssignTask> assignTaskMap = new HashMap<>();
        Map<String, BigDecimal> taskScheduleMap = new HashMap<>();
        Map<String, Integer> taskStatusMap = new HashMap<>();
        Map<String, TradeOrderVo> tradeOrderVoMap = new HashMap<>();
        List<Group> groups = groupMapper.selectList(new QueryWrapper<Group>().orderByDesc("sort"));
        if (groups.size() > 0) {
            groupMap.putAll(groups.stream().collect(Collectors.toMap(Group::getId, Group::getGroupName)));

            Map<String, String> spinnerMap = new HashMap<>();
            List<String> groupIds = groups.stream().map(Group::getId).collect(Collectors.toList());
            List<GroupSpinner> groupSpinners = groupSpinnerMapper.selectList(new QueryWrapper<GroupSpinner>().in("group_id", groupIds));
            if (groupSpinners.size() > 0) {
                List<String> spinnerIds = groupSpinners.stream().map(GroupSpinner::getSpinnerId).collect(Collectors.toList());
                List<Spinner> spinners = spinnerMapper.selectBatchIds(spinnerIds);
                if (spinners.size() > 0)
                    spinnerMap.putAll(spinners.stream().collect(Collectors.toMap(Spinner::getId, Spinner::getOperateId)));
            }
            for (GroupSpinner groupSpinner : groupSpinners)
                groupSpinnerMap.put(groupSpinner.getGroupId(), commonUtil.getOperatorById(spinnerMap.get(groupSpinner.getSpinnerId())).getRealName());

            groupStations.addAll(groupStationMapper.selectList(new QueryWrapper<GroupStation>().in("group_id", groupIds)));

            if (groupStations.size() > 0) {
                List<String> stationIds = groupStations.stream().map(GroupStation::getStationId).collect(Collectors.toList());

                // 刷卡信息
                List<SwipeCardInfo> swipeCardInfos = swipeCardInfoMapper.selectList(new QueryWrapper<SwipeCardInfo>().in("station_id", stationIds));
                if (swipeCardInfos.size() > 0) {
                    swipeCardInfoMap.putAll(swipeCardInfos.stream().collect(Collectors.toMap(SwipeCardInfo::getStationId, c -> c)));

                    List<String> assignTaskId = swipeCardInfos.stream().map(SwipeCardInfo::getAssignTaskId).collect(Collectors.toList());
                    // 派工信息
                    List<AssignTask> assignTasks = assignTaskMapper.selectBatchIds(assignTaskId);
                    assignTaskMap.putAll(assignTasks.stream().collect(Collectors.toMap(AssignTask::getStationId, c -> c)));

                    // 进度
                    Set<String> proTaskDetailIds = assignTasks.stream().map(AssignTask::getTaskDetailId).collect(Collectors.toSet());
                    List<TradeOrderVo> tradeOrderVos = proTaskDetailMapper.selectTradeOrderCode(proTaskDetailIds);
                    if (tradeOrderVos.size() > 0)
                        tradeOrderVoMap.putAll(tradeOrderVos.stream().collect(Collectors.toMap(TradeOrderVo::getProTaskDetailId, c -> c)));

                    List<AssignTask> all = assignTaskMapper.selectList(new QueryWrapper<AssignTask>()
                            .in("task_detail_id", proTaskDetailIds));
                    List<ProTaskDetail> proTaskDetails = proTaskDetailMapper.selectBatchIds(proTaskDetailIds);
                    Map<String, ProTaskDetail> proTaskDetailMap = proTaskDetails.stream().collect(Collectors.toMap(ProTaskDetail::getId, c -> c));
                    Map<String, List<AssignTask>> assignTaskGroup = all.stream().collect(Collectors.groupingBy(AssignTask::getTaskDetailId));
                    for (String taskDetailId : assignTaskGroup.keySet()) {
                        ProTaskDetail proTaskDetail = proTaskDetailMap.get(taskDetailId);
                        if (proTaskDetail == null)
                            return BizResult.fail("对应生产明细不存在");

                        List<AssignTask> collect = assignTaskGroup.get(taskDetailId);
                        BigDecimal taskFinishQty = BigDecimal.ZERO;
                        if (collect != null)
                            taskFinishQty = collect.stream().map(AssignTask::getCompleteQty).reduce(BigDecimal.ZERO, BigDecimal::add);

                        BigDecimal taskSchedule = taskFinishQty
                                .divide(BigDecimal.valueOf(proTaskDetail.getNumber()), 4, RoundingMode.HALF_UP)
                                .multiply(BigDecimal.valueOf(100));
                        taskScheduleMap.put(taskDetailId, taskSchedule);

                        int taskStatus = 1;
                        if (proTaskDetail.getWarnQty() != null) {
                            if (taskFinishQty.compareTo(BigDecimal.valueOf(proTaskDetail.getNumber())) >= 0)
                                taskStatus = 3;
                            else if (taskFinishQty.compareTo(proTaskDetail.getWarnQty()) >= 0)
                                taskStatus = 2;
                        }
                        taskStatusMap.put(taskDetailId, taskStatus);
                    }

                }

            }
        }

        List<PcMonitorDto> list = new ArrayList<>();
        for (GroupStation groupStation : groupStations) {
            String stationCode = commonUtil.getStationById(groupStation.getStationId()).getStationCode();
            if (StringUtils.isNotBlank(param.getStationCode()))
                if (!stationCode.contains(param.getStationCode()))
                    continue;

            SwipeCardInfo swipeCardInfo = swipeCardInfoMap.get(groupStation.getStationId());

            String tradeOrderCode = null;
            if (StringUtils.isNotBlank(param.getTradeOrderCode()) && swipeCardInfo == null)
                continue;
            else if (StringUtils.isNotBlank(param.getTradeOrderCode())) {
                TradeOrderVo tradeOrderVo = tradeOrderVoMap.get(swipeCardInfo.getProTaskDetailId());
                if (tradeOrderVo == null)
                    continue;
                if (!tradeOrderVo.getTradeOrderCode().contains(param.getTradeOrderCode()))
                    continue;
                tradeOrderCode = tradeOrderVo.getTradeOrderCode();
            } else if (swipeCardInfo != null) {
                TradeOrderVo tradeOrderVo = tradeOrderVoMap.get(swipeCardInfo.getProTaskDetailId());
                if (tradeOrderVo != null) {
                    tradeOrderCode = tradeOrderVo.getTradeOrderCode();
                }
            }

            String khStyle = null;
            if (StringUtils.isNotBlank(param.getKhStyle()) && swipeCardInfo == null)
                continue;
            else if (StringUtils.isNotBlank(param.getKhStyle())) {
                TradeOrderVo tradeOrderVo = tradeOrderVoMap.get(swipeCardInfo.getProTaskDetailId());
                if (tradeOrderVo == null)
                    continue;
                if (!tradeOrderVo.getKhStyle().contains(param.getKhStyle()))
                    continue;
                khStyle = tradeOrderVo.getKhStyle();
            } else if (swipeCardInfo != null) {
                TradeOrderVo tradeOrderVo = tradeOrderVoMap.get(swipeCardInfo.getProTaskDetailId());
                if (tradeOrderVo != null) {
                    khStyle = tradeOrderVo.getKhStyle();
                }
            }

            String styleCode = swipeCardInfo == null ? null : swipeCardInfo.getStyleCode();
            if (StringUtils.isNotBlank(param.getStyleCode())) {
                if (styleCode == null)
                    continue;
                if (!styleCode.contains(param.getStyleCode()))
                    continue;
            }

            AssignTask assignTask = assignTaskMap.get(groupStation.getStationId());
            PcMonitorDto build = PcMonitorDto.builder()
                    .stationId(groupStation.getStationId())
                    .workshop(commonUtil.getWorkshopById(groups.get(0).getWorkshopId()))
                    .groupName(groupMap.get(groupStation.getGroupId()))
                    .stationCode(stationCode)
                    .status(commonUtil.getStationStatus(groupStation.getStationId()))
                    .styleCode(styleCode)
                    .colorMain(swipeCardInfo == null ? null : swipeCardInfo.getColorMain())
                    .size(swipeCardInfo == null ? null : swipeCardInfo.getSize())
                    .assignQty(assignTask == null ? BigDecimal.ZERO : assignTask.getAssignQty())
                    .finishQty(assignTask == null ? BigDecimal.ZERO : assignTask.getCompleteQty())
                    .tradeOrderCode(tradeOrderCode)
                    .khStyle(khStyle)
                    .stationSchedule(assignTask == null ?
                            null :
                            assignTask.getCompleteQty()
                                    .divide(assignTask.getAssignQty(), 4, RoundingMode.HALF_UP)
                                    .multiply(BigDecimal.valueOf(100)))
                    .taskSchedule(assignTask == null ? null : taskScheduleMap.get(assignTask.getTaskDetailId()))
                    .taskStatus(assignTask == null ? null : taskStatusMap.get(assignTask.getTaskDetailId()))
                    .needle(swipeCardInfo == null ? null : swipeCardInfo.getNeedle())
                    .build();
            if (param.getStatus() != null && !param.getStatus().equals(build.getStatus()))
                continue;
            if (param.getTaskStatus() != null && !param.getTaskStatus().equals(build.getTaskStatus()))
                continue;
            if (StringUtils.isNotBlank(param.getColorMain()) &&
                    !param.getColorMain().equals(build.getColorMain()))
                continue;
            if (StringUtils.isNotBlank(param.getSizeCode()) &&
                    !param.getSizeCode().equals(build.getSize()))
                continue;

            list.add(build);
        }

        // 排序
        list.sort((o1, o2) -> {
            String[] parts1 = o1.getStationCode().split("-");
            String[] parts2 = o2.getStationCode().split("-");

            int num1 = Integer.parseInt(parts1[0].substring(1) + parts1[1] + parts1[2]);
            int num2 = Integer.parseInt(parts2[0].substring(1) + parts2[1] + parts2[2]);

            return Integer.compare(num1, num2);
        });
        return BizResult.success(PageResult.page(param.getCurrent(), param.getSize(), list));
    }

    /**
     * 获取小组
     *
     * @return
     */
    @IgnoreTenant
    @Override
    public BizResult<List<Group>> groupList() {
        List<Group> groups = groupMapper.selectList(
                new QueryWrapper<Group>()
                        .eq("workshop_id", "523cd11213f4f82407b75880f941ee88")
                        .orderByAsc("sort")
        );
        return BizResult.success(groups);
    }

    /**
     * pc端机台监控页面
     *
     * @param param
     * @return
     */
    @Override
    public BizResult<PcMonitorDetailDto> stationRecordMonitor(StationRecordMonitorParam param) {
        QueryWrapper<StationClassRecord> queryWrapper = new QueryWrapper<StationClassRecord>()
                .eq("current_day", param.getDate())
                .eq("workshop_class_id", param.getWorkshopClassId())
                .orderByAsc("create_time");
        if (StringUtils.isNotBlank(param.getStationCode()))
            queryWrapper.like("station_code", param.getStationCode());

        List<StationClassRecord> list = stationClassRecordMapper.selectList(queryWrapper);

        Map<String, StationWithGroupNameVo> groupNameVoMap = new HashMap<>();
        List<StationWithGroupNameVo> stationWithGroupNameVos = groupStationMapper.selectStationWithGroupName();
        for (StationWithGroupNameVo stationWithGroupNameVo : stationWithGroupNameVos)
            groupNameVoMap.put(stationWithGroupNameVo.getStationId(), stationWithGroupNameVo);

        List<PcRunMonitorDto> result = new ArrayList<>();
        if (list.size() > 0) {
            // 排序
            list = list.stream()
                    .sorted(Comparator.comparing(c -> c.getStationCode().replace("-", "")))
                    .collect(Collectors.toList());

            Map<String, List<ReportRecord>> reportRecordMap = new HashMap<>();
            Map<String, SwipeCardInfo> swipeCardInfoMap = new HashMap<>();
            Map<String, BigDecimal> makeTimeMap = new HashMap<>();

            // 当前班次开始和结束时间
            WorkshopClasses workshopClasses = workshopClassesMapper.selectById(param.getWorkshopClassId());
            if (workshopClasses == null)
                return BizResult.fail("班次不存在");

            Date beginTime = DateUtil.formatStringToDate(param.getDate() + " " + workshopClasses.getStartTime() + ":00");
            Date endTime = DateUtil.formatStringToDate(param.getDate() + " " + workshopClasses.getEndTime() + ":00");
            if (beginTime == null || endTime == null)
                return BizResult.fail("班次时间不正确");
            if (beginTime.compareTo(endTime) > 0) {
                // 开始时间大于结束时间 跨天了 结束是指定时间的下一天
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(endTime);
                calendar.add(Calendar.DATE, 1);
                endTime = calendar.getTime();
            }

            List<String> stationIds = list.stream().map(StationClassRecord::getStationId).collect(Collectors.toList());
            // 获取报工记录
            if (stationIds.size() > 0) {
                List<ReportRecord> reportRecords = reportRecordMapper.selectList(
                        new QueryWrapper<ReportRecord>()
                                .in("station_id", stationIds)
                                .between("create_time", beginTime, endTime)
                );
                if (reportRecords.size() > 0)
                    reportRecordMap.putAll(reportRecords.stream().collect(Collectors.groupingBy(ReportRecord::getStationId)));

                // 获取打样时间
                List<StationMakeTimeVo> stationMakeTimeVos = proTaskDetailMapper.selectMakeTime(stationIds, beginTime, endTime);
                if (stationMakeTimeVos.size() > 0) {
                    Map<String, List<StationMakeTimeVo>> stationMakeTimeMap = stationMakeTimeVos.stream().collect(Collectors.groupingBy(StationMakeTimeVo::getStationId));
                    for (String key : stationMakeTimeMap.keySet()) {
                        List<StationMakeTimeVo> timeVos = stationMakeTimeMap.get(key);
                        BigDecimal makeTime = timeVos.stream().map(c -> c.getMakeTime() == null ? BigDecimal.ZERO : c.getMakeTime()).reduce(BigDecimal.ZERO, BigDecimal::add);
                        makeTimeMap.put(key, makeTime);
                    }
                }
            }

            // 获取当前刷卡记录
            List<SwipeCardInfo> swipeCardInfos = swipeCardInfoMapper.selectList(new QueryWrapper<SwipeCardInfo>().in("station_id", stationIds));
            if (swipeCardInfos.size() > 0)
                swipeCardInfoMap.putAll(swipeCardInfos.stream().collect(Collectors.toMap(SwipeCardInfo::getStationId, c -> c)));


            for (StationClassRecord record : list) {
                BigDecimal report = BigDecimal.ZERO;
                List<ReportRecord> reportRecords = reportRecordMap.get(record.getStationId());
                String realName = null;
                String userNo = null;
                if (reportRecords != null && reportRecords.size() > 0) {
                    report = reportRecords.stream().map(ReportRecord::getBookJobQty).reduce(BigDecimal.ZERO, BigDecimal::add);

                    Optional<ReportRecord> firstReportRecord = reportRecords.stream()
                            .sorted(Comparator.comparing(ReportRecord::getCreateTime).reversed())
                            .findFirst();
                    if (firstReportRecord.isPresent()) {
                        realName = firstReportRecord.get().getRealName();
                        userNo = firstReportRecord.get().getUserNo();
                    }
                }

                String styleCode = null;
                String colorMain = null;
                String size = null;
                SwipeCardInfo swipeCardInfo = swipeCardInfoMap.get(record.getStationId());
                if (swipeCardInfo != null) {
                    styleCode = swipeCardInfo.getStyleCode();
                    colorMain = swipeCardInfo.getColorMain();
                    size = swipeCardInfo.getSize();
                }

                int makeTime = 0;
                BigDecimal makeTimeBigDecimal = makeTimeMap.get(record.getStationId());
                if (makeTimeBigDecimal != null)
                    makeTime = makeTimeBigDecimal.intValue();

                StationWithGroupNameVo stationWithGroupNameVo = groupNameVoMap.get(record.getStationId());
                result.add(PcRunMonitorDto.builder()
                        .stationRecordId(record.getId())
                        .stationId(record.getStationId())
                        .stationCode(record.getStationCode())
                        .groupId(stationWithGroupNameVo == null ? null : stationWithGroupNameVo.getGroupId())
                        .groupName(stationWithGroupNameVo == null ? null : stationWithGroupNameVo.getGroupName())
                        .workshop(record.getWorkshopName())
                        .wholeTime(record.getProduceTime())
                        .runTime(record.getRunTime())
                        .idleTime(record.getIdleTime())
                        .faultTime(record.getFaultTime())
                        .stopTime(record.getStopTime())
                        .makeTime(makeTime)
                        .equipmentName(record.getEquipmentName())
                        .currentStyleCode(styleCode)
                        .colorMain(colorMain)
                        .size(size)
                        .bookJobQty(report)
                        .status(commonUtil.getStationStatus(record.getStationId()))
                        .oee(record.getOee())
                        .realName(realName)
                        .userNo(userNo)
                        .build());
            }
        }

        // 筛选
        if (StringUtils.isNotBlank(param.getStyleCode()))
            result = result.stream().filter(c -> c.getCurrentStyleCode() != null && c.getCurrentStyleCode().contains(param.getStyleCode())).collect(Collectors.toList());
        if (StringUtils.isNotBlank(param.getColorMain()))
            result = result.stream().filter(c -> c.getColorMain() != null && c.getColorMain().contains(param.getColorMain())).collect(Collectors.toList());
        if (StringUtils.isNotBlank(param.getFootage()))
            result = result.stream().filter(c -> c.getSize() != null && c.getSize().contains(param.getFootage())).collect(Collectors.toList());
        if (StringUtils.isNotBlank(param.getGroupId()))
            result = result.stream().filter(c -> c.getGroupId() != null && c.getGroupId().equals(param.getGroupId())).collect(Collectors.toList());

        PcMonitorDetailDto res = PcMonitorDetailDto.builder()
                .stationQty(0)
                .runQty(0)
                .idleQty(0)
                .faultQty(0)
                .stopQty(0)
                .sumOee(BigDecimal.ZERO)
                .pageResult(result)
                .build();
        if (result.size() > 0) {
            long stopQty = result.stream().filter(c -> c.getStatus() == 0).count();
            long runQty = result.stream().filter(c -> c.getStatus() == 1).count();
            long idleQty = result.stream().filter(c -> c.getStatus() == 2).count();
            long faultQty = result.stream().filter(c -> c.getStatus() == 3).count();
            BigDecimal allOee = result.stream()
                    .map(PcRunMonitorDto::getOee)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            res.setStationQty(result.size());
            res.setStopQty(Integer.parseInt(String.valueOf(stopQty)));
            res.setRunQty(Integer.parseInt(String.valueOf(runQty)));
            res.setIdleQty(Integer.parseInt(String.valueOf(idleQty)));
            res.setFaultQty(Integer.parseInt(String.valueOf(faultQty)));

            res.setSumOee(
                    BigDecimal.ZERO.compareTo(allOee) == 0 ?
                            BigDecimal.ZERO :
                            allOee.divide(BigDecimal.valueOf(result.size()), 2, RoundingMode.HALF_UP));
        }

        return BizResult.success(res);
    }

    /**
     * pc端机台监控页面获取机台状态信息
     *
     * @param param
     * @return
     */
    @Override
    public BizResult<List<StationStatusDto>> stationStatus(StationStatusParam param) {
        List<StationStatusDto> res = new ArrayList<>();
        try {
            // 查询条件
            String indexName = Constant.ES_INDEX.STATION_STATUS_RECORD_INDEX;
            Map<String, Object> andMap = new HashMap<>();
            andMap.put("stationId", param.getStationId());

            Map<String, Object> timeRangeMap = new HashMap<>();
            String beginTimeStr = param.getDate() + " " + param.getClassBeginTime() + ":00";
            String endTimeStr = param.getDate() + " " + param.getClassEndTime() + ":00";
            Date beginTimeEs = DateUtil.formatStringToDate(beginTimeStr, DateUtil.DEFAULT_DATE_FORMAT);
            Date endTimeEs = DateUtil.formatStringToDate(endTimeStr, DateUtil.DEFAULT_DATE_FORMAT);
            if (beginTimeEs.compareTo(endTimeEs) > 0) {
                // 开始时间大于结束时间 跨天
                endTimeEs = DateUtil.dateAddDay(endTimeEs, 1);
                timeRangeMap.put("startTime", beginTimeEs.getTime());
                timeRangeMap.put("endTime", endTimeEs.getTime());
            } else {
                timeRangeMap.put("startTime", beginTimeEs.getTime());
                timeRangeMap.put("endTime", endTimeEs.getTime());
            }

            List<StationStatusVo> list = new ArrayList<>();
            List<JSONObject> jsonObjects = restHighLevelUtils.customConditionSearch(indexName, andMap, timeRangeMap);
            if (jsonObjects.size() > 0) {
                list.addAll(jsonObjects.stream().map(c -> JSONObject.parseObject(JSON.toJSONString(c), StationStatusVo.class)).collect(Collectors.toList()));
                list.sort(Comparator.comparing(StationStatusVo::getCreateTime));
            }

            for (int i = 0; i < list.size(); i++) {
                if (i + 1 == list.size()) {
                    // 最后一条数据
                    StationStatusVo current = list.get(i);

                    // 班次开始和结束时间
                    Date classBeginTime = DateUtil.formatStringToDate(current.getToday() + " " + current.getClassBeginTime() + ":00");
                    Date classEndTime = DateUtil.formatStringToDate(current.getToday() + " " + current.getClassEndTime() + ":00");
                    if (classBeginTime == null || classEndTime == null) {
                        log.error("====[ERROR]====MonitorServiceImpl====stationStatus classBeginTime or classEndTime is null");
                        break;
                    }
                    if (classBeginTime.compareTo(classEndTime) > 0) {
                        // 开始时间大于结束时间 跨天了 结束是指定时间的下一天
                        Calendar calendar = Calendar.getInstance();
                        calendar.setTime(classEndTime);
                        calendar.add(Calendar.DATE, 1);
                        classEndTime = calendar.getTime();
                    }

                    String beginTime = DateUtil.formatDateToString(current.getCreateTime(), DateUtil.DEFAULT_DATE_FORMAT);
                    String endTime = DateUtil.formatDateToString(classEndTime, DateUtil.DEFAULT_DATE_FORMAT);
                    // 判断当前时间是否在班次结束时间之前
                    if (new Date().compareTo(classEndTime) < 0)
                        // 当前时间在班次结束时间之前
                        endTime = DateUtil.formatDateToString(new Date(), DateUtil.DEFAULT_DATE_FORMAT);

                    Integer interval = DateUtil.betweenSecond(beginTime, endTime);
                    res.add(StationStatusDto.builder()
                            .uuid(current.getUuid())
                            .status(current.getStatus())
                            .beginTime(beginTime)
                            .endTime(endTime)
                            .duration(interval)
                            .build());

                    break;
                }
                StationStatusVo current = list.get(i);
                String beginTime = DateUtil.formatDateToString(current.getCreateTime(), DateUtil.DEFAULT_DATE_FORMAT);
                StationStatusVo next = list.get(i + 1);
                String endTime = DateUtil.formatDateToString(next.getCreateTime(), DateUtil.DEFAULT_DATE_FORMAT);
                Integer interval = DateUtil.betweenSecond(beginTime, endTime);

                res.add(StationStatusDto.builder()
                        .uuid(current.getUuid())
                        .status(current.getStatus())
                        .beginTime(beginTime)
                        .endTime(endTime)
                        .duration(interval)
                        .build());
            }

        } catch (Exception e) {
            log.error("====[ERROR]====MonitorServiceImpl====stationStatus 获取机台状态变更失败 e:{}", e.getMessage());
        }
        return BizResult.success(res);
    }

    /**
     * pc端机台时长监控页面导出
     *
     * @param param
     * @param response
     */
    @Override
    public BizResult<?> stationRecordMonitorExport(StationRecordMonitorParam param, HttpServletResponse response) {
        BizResult<PcMonitorDetailDto> pcMonitorDetailDtoBizResult = stationRecordMonitor(param);

        List<PcRunMonitorDto> record = pcMonitorDetailDtoBizResult.getData().getPageResult();
        List<PcRunMonitorExcelDto> excels = record.stream().map(c -> {
            PcRunMonitorExcelDto build = PcRunMonitorExcelDto.builder().build();
            BeanUtils.copyProperties(c, build);
            return build;
        }).collect(Collectors.toList());
        try {
            ServletOutputStream outputStream = response.getOutputStream();

            Workbook sheets = ExcelExportUtil.exportExcel(
                    new ExportParams("车间运行监控信息", "车间运行监控"),
                    PcRunMonitorExcelDto.class,
                    excels
            );


            Sheet sheet = sheets.getSheetAt(0);
            int lastRowNum = sheet.getLastRowNum();
            CellStyle cellStyle = sheet.getRow(lastRowNum).getCell(0).getCellStyle();
            Row row = sheet.createRow(lastRowNum + 1);

            Cell cell1 = row.createCell(0);
            cell1.setCellValue("故障台数:" + pcMonitorDetailDtoBizResult.getData().getFaultQty());
            cell1.setCellStyle(cellStyle);
            Cell cell2 = row.createCell(1);
            cell2.setCellValue("待机台数:" + pcMonitorDetailDtoBizResult.getData().getIdleQty());
            cell2.setCellStyle(cellStyle);
            Cell cell3 = row.createCell(2);
            cell3.setCellValue("关机台数:" + pcMonitorDetailDtoBizResult.getData().getStopQty());
            cell3.setCellStyle(cellStyle);
            Cell cell4 = row.createCell(3);
            cell4.setCellValue("正常台数:" + pcMonitorDetailDtoBizResult.getData().getRunQty());
            cell4.setCellStyle(cellStyle);
            Cell cell5 = row.createCell(4);
            cell5.setCellValue("平均稼动率:" + pcMonitorDetailDtoBizResult.getData().getSumOee() + "%");
            cell5.setCellStyle(cellStyle);

            //设置请求头,解决文件名中文乱码问题
            response.setHeader("content-disposition", "attachment;fileName=" + URLEncoder.encode("车间运行监控.xls", "utf-8"));
            sheets.write(outputStream);
            outputStream.close();
            sheets.close();

            return BizResult.success();
        } catch (Exception e) {
            log.error("====[ERROR]====MonitorServiceImpl====stationRecordMonitorExport 导出失败 e:{}", e.getMessage());
            return BizResult.fail("导出失败");
        }
    }

    /**
     * pc端编制抽检明细报表
     *
     * @param param
     * @return
     */
    @Override
    public BizResult<PageResult<SpotCheckDetailDto>> spotCheckDetail(SpotCheckDetailParam param) {
        QueryWrapper<SpotCheck> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(param.getDate()))
            queryWrapper.eq("date", param.getDate());
        if (StringUtils.isNotBlank(param.getStationCode()))
            queryWrapper.like("station_code", param.getStationCode());
        if (StringUtils.isNotBlank(param.getStyleCode()))
            queryWrapper.like("style_code", param.getStyleCode());
        if (StringUtils.isNotBlank(param.getSpinner()))
            queryWrapper.like("spinner", param.getSpinner());

        List<SpotCheck> list = spotCheckMapper.selectList(
                queryWrapper.orderByDesc("create_time"));

        List<SpotCheckDetailDto> convert = list.stream().map(c -> {
            SpotCheckDetailDto build = SpotCheckDetailDto.builder().build();
            BeanUtils.copyProperties(c, build);
            build.setSpotCheckId(c.getId());
            build.setCreateTime(DateUtil.formatDateToString(c.getCreateTime()));
            return build;
        }).collect(Collectors.toList());

        if (!convert.isEmpty())
            convert.sort((record1, record2) -> record2.getDate().compareTo(record1.getDate()));

        return BizResult.success(PageResult.page(param.getCurrent(), param.getSize(), convert));
    }

    /**
     * pc端编制抽检明细报表导出
     *
     * @param param
     * @param response
     * @return
     */
    @Override
    public BizResult<?> spotCheckDetailExport(SpotCheckDetailParam param, HttpServletResponse response) {
        BizResult<PageResult<SpotCheckDetailDto>> result = spotCheckDetail(param);
        if (result.getData().getRecord() == null || result.getData().getRecord().size() == 0)
            return BizResult.fail("无法导出空数据");

        List<SpotCheckDetailDto> record = result.getData().getRecord();
        List<SpotCheckDetailExcelDto> excels = new ArrayList<>();
        for (int i = 0; i < record.size(); i++) {
            SpotCheckDetailExcelDto build = SpotCheckDetailExcelDto.builder().build();
            BeanUtils.copyProperties(record.get(i), build);
            build.setSeq(String.valueOf(i + 1));
            build.setSpotCheckQty(record.get(i).getSpotCheckQty() == null ? "-" : String.valueOf(record.get(i).getSpotCheckQty()));
            build.setRejectQty(record.get(i).getRejectQty() == null ? "-" : String.valueOf(record.get(i).getRejectQty()));
            build.setPassRate(record.get(i).getPassRate() == null ? "-" : String.valueOf(record.get(i).getPassRate()));
            excels.add(build);
        }

        try {
            ServletOutputStream outputStream = response.getOutputStream();

            Workbook sheets = ExcelExportUtil.exportExcel(
                    new ExportParams("编制抽检明细报表", "编制抽检明细"),
                    SpotCheckDetailExcelDto.class,
                    excels
            );
            //设置请求头,解决文件名中文乱码问题
            response.setHeader("content-disposition", "attachment;fileName=" + URLEncoder.encode("编制抽检明细报表.xls", "utf-8"));
            sheets.write(outputStream);
            outputStream.close();
            sheets.close();

            return BizResult.success();
        } catch (Exception e) {
            log.error("====[ERROR]====MonitorServiceImpl====spotCheckDetailExport 导出失败 e:{}", e.getMessage());
            return BizResult.fail("导出失败");
        }
    }

    /**
     * pc端编制抽检统计报表
     *
     * @param param
     * @return
     */
    @Override
    public BizResult<PageResult<SpotCheckStatisticsDto>> spotCheckStatistics(SpotCheckStatisticsParam param) {
        QueryWrapper<SpotCheck> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(param.getStationCode()))
            queryWrapper.like("station_code", param.getStationCode());
        if (StringUtils.isNotBlank(param.getBeginDate())) {
            String beginTime = param.getBeginDate() + " 00:00:00";
            queryWrapper.gt("create_time", DateUtil.formatStringToDate(beginTime));
        }
        if (StringUtils.isNotBlank(param.getEndDate())) {
            String endTime = param.getEndDate() + " 23:59:59";
            queryWrapper.lt("create_time", DateUtil.formatStringToDate(endTime));
        }

        List<SpotCheckStatisticsDto> list = new ArrayList<>();
        List<SpotCheck> spotChecks = spotCheckMapper.selectList(queryWrapper.orderByAsc("create_time"));
        if (spotChecks.size() > 0) {
            Map<String, List<SpotCheck>> collect = spotChecks.stream()
                    .collect(Collectors.groupingBy(SpotCheck::getStationCode));

            for (String key : collect.keySet()) {
                List<SpotCheck> checks = collect.get(key);
                Integer spotCheckQty = checks.stream().map(c -> c.getSpotCheckQty() == null ? 0 : c.getSpotCheckQty()).reduce(0, Integer::sum);
                Integer rejectQty = checks.stream().map(c -> c.getRejectQty() == null ? 0 : c.getRejectQty()).reduce(0, Integer::sum);

                list.add(SpotCheckStatisticsDto.builder()
                        .stationCode(key)
                        .spotCheckQty(spotCheckQty)
                        .rejectQty(rejectQty)
                        .passRate(spotCheckQty == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(spotCheckQty - rejectQty)
                                .divide(BigDecimal.valueOf(spotCheckQty), 4, RoundingMode.HALF_UP)
                                .multiply(BigDecimal.valueOf(100)))
                        .build());
            }
        }

        return BizResult.success(PageResult.page(param.getCurrent(), param.getSize(), list));
    }

    /**
     * pc端编制抽检统计报表导出
     *
     * @param param
     * @param response
     * @return
     */
    @Override
    public BizResult<?> spotCheckStatisticsExport(SpotCheckStatisticsParam param, HttpServletResponse response) {
        BizResult<PageResult<SpotCheckStatisticsDto>> result = spotCheckStatistics(param);
        if (result.getData().getRecord() == null || result.getData().getRecord().size() == 0)
            return BizResult.fail("无法导出空数据");

        List<SpotCheckStatisticsDto> record = result.getData().getRecord();
        List<SpotCheckStatisticsExcelDto> excels = new ArrayList<>();
        for (int i = 0; i < record.size(); i++) {
            excels.add(SpotCheckStatisticsExcelDto.builder()
                    .seq(String.valueOf(i + 1))
                    .stationCode(record.get(i).getStationCode())
                    .spotCheckQty(String.valueOf(record.get(i).getSpotCheckQty()))
                    .rejectQty(String.valueOf(record.get(i).getRejectQty()))
                    .passRate(String.valueOf(record.get(i).getPassRate()))
                    .build());
        }

        try {
            ServletOutputStream outputStream = response.getOutputStream();

            Workbook sheets = ExcelExportUtil.exportExcel(
                    new ExportParams("编制抽检统计报表", "编制抽检统计"),
                    SpotCheckStatisticsExcelDto.class,
                    excels
            );
            //设置请求头,解决文件名中文乱码问题
            response.setHeader("content-disposition", "attachment;fileName=" + URLEncoder.encode("编制抽检统计报表.xls", "utf-8"));
            sheets.write(outputStream);
            outputStream.close();
            sheets.close();

            return BizResult.success();
        } catch (Exception e) {
            log.error("====[ERROR]====MonitorServiceImpl====spotCheckStatisticsExport 导出失败 e:{}", e.getMessage());
            return BizResult.fail("导出失败");
        }
    }

    /**
     * pc端编制抽检明细删除
     *
     * @param spotCheckId
     * @return
     */
    @Override
    public BizResult<?> spotCheckDetailDelete(String spotCheckId) {
        spotCheckMapper.deleteById(spotCheckId);
        return BizResult.success();
    }

}
